class Trial {
  //Trials consist of 5 stages
  
  // 1 - Wait for observing / orienting response
  // 2 - Present the sample stimulus, wait for press + limited hold
  // 3 - Blackout ~200ms
  // 4 - Present comparison stimuli, wait for press + limited hold
  // 5 - blackout and maybe reinforcement
  
  int stage;
  
  long trial_start_time;
  long stage_start_time;
  
  boolean finished;
  
  // Default limited hold values can be entered here
  // though they may be overridden by stage_X_setup if 
  // they need to vary each trial. They are expressed
  // in milliseconds
  long stage_1_limited_hold;
  long stage_2_limited_hold=5000; //How long we show the sample e.g., 2000
  long stage_3_limited_hold;
  long stage_4_limited_hold=1000; //Presentation of comparison stimuli
  long stage_5_limited_hold=1000; // correct response -> Sr consumption time + ITI
  long stage_6_limited_hold=1000; // Incorrect Response -> just ITI
  long stage_7_limited_hold=1000; // no response -> just ITI
  
  int stage_4_consequence; // What's going to happen in stage 5?
                           // 0 - undefined
                           // 1 - signal reinforcement
                           // 2 - incorrect response
  
  int sample_position=-1;
  
  StimulusSet sample;
  StimulusSet comparison_1;
  StimulusSet comparison_2;
  StimulusSet uncertainty_r;
  
  long stage_4_latency;

  
  Trial(int _sample, int _comparison_1, int _comparison_2, int _uncertainty_r) {
    sample = new StimulusSet(_sample);
    comparison_1 = new StimulusSet(_comparison_1);
    comparison_2 = new StimulusSet(_comparison_2);
    if (_uncertainty_r > 0) uncertainty_r = new StimulusSet();

    stage = -1;
    trial_start_time = -1;
    stage_start_time = -1;
    finished = false;
    //println("Creating new trial");
    //println(" Sample = " + _sample);
    //println(" Comparison 1 = " + _comparison_1);
    //println(" Comparison 2 = " + _comparison_2);
    //println(" UncertaintyR = " + _uncertainty_r);
  }
  
  void gotoStage(int newstage) {
    stage = newstage;
    stage_start_time = -1;
    //println("New Stage: " + stage);
    if (newstage == 2) {
      stage_2_setup();
    } else if (newstage == 3) {
      stage_3_setup();
    }else if (newstage == 4) {
      stage_4_setup();
    } else if (newstage == 5) {
      stage_5_setup();
    } else if (newstage == 6) {
      stage_6_setup();
    } else if (newstage == 7) {
      stage_7_setup();
    }
  }
  
  
  //
  // Stage 1 - Wait for user input
  //
  void stage_1_draw() {
    background(0);
    fill(255,255,0);
    rectMode(CENTER);
    rect(width/2,height/2,width/4,height/4);
  }
  void stage_1_click() {
    if ((mouseX >= width/3) && (mouseX <= width*2/3) && (mouseY >= height/3) && (mouseY <= height*2/3)) {
      gotoStage(2);
    }
  }
  
  
  //
  // Stage 2 - Show the sample stimulus
  //
  void stage_2_setup() {
    sample.position = int(random(1,9));
  }
  void stage_2_draw() {
    background(0);
   
    sample.drawAnimatedStimulus(-1,millis()-stage_start_time,stage_2_limited_hold);
    if (millis()-stage_start_time > stage_2_limited_hold) {
      gotoStage(3);
    }
  }
  void stage_2_click() {
    if (sample.click()) gotoStage(3);
  }
  
  
  //
  // Stage 3 - Brief Blackout
  //
  void stage_3_setup() {
    stage_3_limited_hold = int(random(90,200));
  }
  void stage_3_draw() {
    background(0);
    if (millis()-stage_start_time > stage_3_limited_hold) {
      gotoStage(4);
    }
  }
  void stage_3_click() {
    //do nothing
  }
  
  
  
  //
  // Stage 4 - Show the comparison stimuli
  //
  void stage_4_setup() {
    comparison_1.position = int(random(1,9));
    while (sample.position == comparison_1.position) {
      comparison_1.position = int(random(1,9));
    }
    comparison_2.position = int(random(1,9));
    while (comparison_1.position == comparison_2.position || sample.position == comparison_2.position) {
      comparison_2.position = int(random(1,9));
    }
    if (uncertainty_r != null) {
      uncertainty_r.position = int(random(1,9));
      while (comparison_1.position == uncertainty_r.position || sample.position == uncertainty_r.position ||
             comparison_2.position == uncertainty_r.position) {
        uncertainty_r.position = int(random(1,9));
      }
    }
  }
  void stage_4_draw() {
    background(0);
    comparison_1.drawStimulus(0);
    comparison_2.drawStimulus(0);
    if (uncertainty_r != null) uncertainty_r.drawStimulus(0);
    if (millis()-stage_start_time > stage_4_limited_hold) {
      gotoStage(7);
    }
  }
  void stage_4_click() {
    if (comparison_1.click()) {
        stage_4_latency = comparison_1.time_clicked - stage_start_time;
        if (comparison_1.num == sample.num) gotoStage(5); //correct
        else gotoStage(6); //incorrect
    } else if (comparison_2.click()) {
        stage_4_latency = comparison_2.time_clicked - stage_start_time;
        if (comparison_2.num == sample.num) gotoStage(5); //correct
        else gotoStage(6); //incorrect
    } else if (uncertainty_r != null) if (uncertainty_r.click()) {
        stage_4_latency = uncertainty_r.time_clicked - stage_start_time;
        gotoStage(5); //This will probably change depending on condition
    }
  }
  
  
  
  
  
  //
  // Stage 5 - This stage is called when a correct response was made
  //
  void stage_5_setup() {
    correctResponse();
  }
  void stage_5_draw() {
    background(0);
    if (comparison_1.time_clicked > 0) comparison_1.drawStimulus(1); // 1 = green for correct
    if (comparison_2.time_clicked > 0) comparison_2.drawStimulus(1);
    if (millis()-stage_start_time > stage_5_limited_hold) {
      background(0);
      finished = true;
    }
  }
  void stage_5_click() {
    
  }
  
  
  //
  // Stage 6 - This stage is called when an incorrect response was made
  //
  void stage_6_setup() {
    incorrectResponse();
  }
  void stage_6_draw() {
    background(0);
    if (comparison_1.time_clicked > 0) comparison_1.drawStimulus(2); // sending a 2 here means that the box should appear Red, for incorrect
    if (comparison_2.time_clicked > 0) comparison_2.drawStimulus(2);
    if (millis()-stage_start_time > stage_6_limited_hold) {
      background(0);
      finished = true;
    }
  }
  void stage_6_click() {
    
  }
  
  
  
  //
  // Stage 7 - No response was mode
  //
  void stage_7_setup() {
    noChoice();
  }
  void stage_7_draw() {
    background(0);
    if (comparison_1.time_clicked > 0) comparison_1.drawStimulus(2); // sending a 2 here means that the box should appear Red, for incorrect
    if (comparison_2.time_clicked > 0) comparison_2.drawStimulus(2);
    if (millis()-stage_start_time > stage_7_limited_hold) {
      background(0);
      finished = true;
    }
  }
  void stage_7_click() {
    
  }
  
  
  
  
  void correctResponse() {
    println(" choice " + min(comparison_1.num,comparison_2.num) + "/" + max(comparison_1.num,comparison_2.num) + " CORRECT,   latency = " + stage_4_latency);
    if (sound_effect_correct != null) sound_effect_correct.trigger();
  }
  
  void incorrectResponse() {
    println(" choice " + min(comparison_1.num,comparison_2.num) + "/" + max(comparison_1.num,comparison_2.num) + " incorrect, latency = " + stage_4_latency);
    if (sound_effect_incorrect != null) sound_effect_incorrect.trigger();
  }
  
  void noChoice() {
    println(" choice " + min(comparison_1.num,comparison_2.num) + "/" + max(comparison_1.num,comparison_2.num) + " none,      latency = " + stage_4_latency);
    if (sound_effect_incorrect != null) sound_effect_incorrect.trigger();
  }
  
  
  void restartTrial() {
    // This is only for testing purposes
    // In a real session, each trial will be created, used once, and then discarded
    trial_start_time = -1;
    stage_start_time = -1;
    stage = -1;
    comparison_1.time_clicked = 0;
    comparison_2.time_clicked = 0;
  }
  
  void drawTrial() {
    if (finished == true) return;
    
    if (trial_start_time == -1) {
      stage_start_time = -1;
      gotoStage(1);
      trial_start_time = millis();
    }
    
    if (stage_start_time == -1) {
      stage_start_time = millis();
    }
    
    if (stage == 1) {
      stage_1_draw();
    } else if (stage == 2) {
      stage_2_draw();
    } else if (stage == 3) {
      stage_3_draw();
    } else if (stage == 4) {
      stage_4_draw();
    } else if (stage == 5) {
      stage_5_draw();
    } else if (stage == 6) {
      stage_6_draw();
    } else if (stage == 7) {
      stage_7_draw();
    }
    
    
  }
  
  void click() {
    if (stage == 1) {
      stage_1_click();
    } else if (stage == 2) {
      stage_2_click();
    } else if (stage == 3) {
      stage_3_click();
    } else if (stage == 4) {
      stage_4_click();
    } else if (stage == 5) {
      stage_5_click();
    } else if (stage == 6) {
      stage_6_click();
    } else if (stage == 7) {
      stage_7_click();
    }
  }
  
}
